<?php

require_once PATH_FFWD.'prototypes/record.base.php';
require_once PATH_FFWD.'core/helpers.php';

if(!CLI)session_start();


class User extends BaseRecord{	
	static $dbo=NULL;
	static $cookiename='user_cookie';
	static $timeout=36000000000;//inactivity timeout
	static $rightCache=Array();	
	static $roles=NULL;
	
	static $tables=Array('account'=>NULL,
											 'login'=>NULL,
											 'roles'=>NULL,
											 'object_role'=>NULL,
											 'settings'=>NULL,
											 'setting_values'=>NULL
	);
	
	public $storage;
	
	public function __construct(&$dbo){
		self::$dbo=&$dbo;
		if(!self::$tables['account']){
			foreach(array_keys(self::$tables) as $k){
				$clsn='User_'.$k.'Table';
				try{
					self::$tables[$k]=new $clsn(); 
				}catch(Exception $e){					
					self::$dbo->buildTable('user_'.$k);
					self::$tables[$k]=new $clsn();								
				};
			};			
		};
		
		if(!isset($_SESSION['user_class_storage']))$_SESSION['user_class_storage']=Array();		
		$this->storage=&$_SESSION['user_class_storage'];
		
		try{
			if(!isset($_COOKIE[self::$cookiename])){
				$e=self::$tables['account']->getById('new');
				foreach($e as $k=>$v)$this->$k=$e->$k;
			}else{
				$this->loginByCookie($_COOKIE[self::$cookiename]);
			};
		}catch(Exception $e){ //table probably does not exist
			$this->buildSQLTables();				
		}		
	}
	
	public function loginByCookie($value){
		$e=self::$tables['account']->getByCookieValue($value);
		if(!$e)$e=self::$tables['account']->getById('new');	
		foreach($e as $k=>$v)$this->$k=$e->$k;
	}
	
	public function __destruct(){
	}
	
	public function getCookieValue(){
		if(isset($_COOKIE[self::$cookiename]))
			return $_COOKIE[self::$cookiename];
		else
			return '';
	}
	
	protected function getDataByCookie($val){
		$rs=self::$dbo->query("SELECT `id`,`user_account_id` FROM `user_login` WHERE `cookievalue`='$val';");
		if(!$rs || !$rs->num_rows)return Array();
		$row=$rs->fetch_assoc();
		self::$dbo->query("UPDATE `user_login` SET `last_access`=now() WHERE `id`=".$row['id']);
		return $this->getDataByUserId($row['user_account_id']);
	}
	
	protected function getDataByUserID($userid){
		$rs=self::$dbo->query("SELECT * FROM `user_account` WHERE `id`=$userid;");
		if(!$rs || !$rs->num_rows)return Array();
		return $rs->fetch_assoc();
	}
	public function __toString(){return (@$this->data['name']?$this->data['name']:'');}		

	public function dologin($p){
		if(!isset($p['name']) || !$p['name'])return 'name must be filled';
		if(!isset($p['password'])|| !$p['password'])return 'password must be filled';
		$name=self::$dbo->escape_string($p['name']);
		$q="SELECT `id`,`password` FROM `user_account` WHERE `name`='$name'";
		try{	
			$rs=self::$dbo->query($q);
		}catch(Exception $e){
			if(self::$dbo->isTableDoesntExistExeption($e)){
				$this->buildSQLTables();
			}			
			exit;
		}
		if(!$rs || !$rs->num_rows)return 'user does not exist';
		$row=$rs->fetch_assoc();
		$userid=$row['id'];
		if(md5($p['password'])!=$row['password'])return 'wrong password';
		$cookievalue=com_create_guid();
		
		self::$dbo->query("INSERT INTO `user_login` SET  `user_account_id`=$userid,".
																										"`cookievalue`='$cookievalue',".
																										"`login_at`=now(),".
																										"`last_access`=now(),".
																										"`remote_address`='".$_SERVER['REMOTE_ADDR']."' ");
		setcookie(self::$cookiename,$cookievalue,time()+self::$timeout,'/');
		$this->data=$this->getDataByUserID($userid);	
		console_log('Successfull login');
		return NULL;
	}	
	
	public function dologout(){
		if(!$this->id)return;
		$q="DELETE FROM `user_login` WHERE `user_account_id`='".(string)$this->id."'";
		if(isset($_COOKIE[self::$cookiename])){
			$q.=" AND `cookievalue`='".$_COOKIE[self::$cookiename]."' ";
			setcookie(self::$cookiename,'',time()-3600,'/');
		};		
		self::$dbo->query($q);
		$this->data=Array();
	}
	
	public function printAvatar($size='64x64'){
		if(!$this->name)return;
		self::printAvatarByName($this->name);
	}
	
	static function printAvatarByName($username,$size='64x64'){
		echo '<img src="/user_pictures/avatars/'.$username.'_'.$size.'.jpg" alt="'.$username.'" />';
	}
	
	public function getRights($object_type,$object_id){
		$user_id=(string)$this->id;
		if($user_id=='new')$user_id='0';
		return self::static_getRights($object_type,$object_id,$user_id);
	}
	
	public function setRole($role,$object_type,$object_id){
		$user_id=(string)$this->id;
		if($user_id=='new')$user_id='0';
		self::static_setRole($role,$object_type,$object_id,$user_id);
	}
	
	static function buildRightCacheLevel(Array $levels,&$p){
		$new=0;
		$p=&self::$rightCache;
		for($i=0;$i<count($levels);$i++){
			if(!isset($p[$levels[$i]])){
				$p[$levels[$i]]=Array();
				$new=1;	
			}
			$p=&$p[$levels[$i]];
		}		
		return $new;		
	}

	static function static_getRights($object_type,$object_id,$user_id,$forceload=0){
		$p=NULL;
		if(!self::$roles)self::loadRoles();
		$levels=Array($user_id,$object_type,$object_id);			
		$new=0;
		$p=&self::$rightCache;
		for($i=0;$i<count($levels);$i++){
			if(!isset($p[$levels[$i]])){
				$p[$levels[$i]]=Array();
				$new=1;	
			}
			$p=&$p[$levels[$i]];
		}	
		if($forceload)$p=Array();
		else	
		if(!$new)return $p;
		
		$q="SELECT UR.`name` FROM `user_object_role` UOR INNER JOIN `user_roles` UR ON UOR.`role_id` = UR.`id` ".
		   " WHERE UOR.`user_id`=".$user_id." AND UOR.`object_type`='".$object_type."' AND UOR.`object_id`=".$object_id." LIMIT 1";
		$rs=self::$dbo->query($q);
		if($rs->num_rows){
			$row=$rs->fetch_assoc();
			$p=self::$roles[$row['name']];
		};		
		//print_var($levels,'req');print_var($p,'res');	
		return $p;
	}	
	
	static function loadRoles(){
		self::$roles=Array();		
		$rs=self::$dbo->query("SELECT * FROM `user_roles` ");
		while($row=$rs->fetch_assoc()){
			self::$roles[$row['name']]=Array('__id'=>$row['id']);
			foreach($row as $k=>$v)if(substr($k,0,4)=='can_' && $v)self::$roles[$row['name']][]=substr($k,4);			
		}
		$rs->free();		
	}
	
	static function static_setRole($arole,$object_type,$object_id,$user_id){
		if(!self::$roles)self::loadRoles();
		if(!isset(self::$roles[$arole]))throw new Exception('The given ROLE does not exists');
		$role=self::$tables['object_role']->getBy(Array(
			'object_type'=>$object_type,
			'object_id'=>$object_id,
			'user_id'=>$user_id,
		));
		if(!$role){
			$role=self::$tables['object_role']->getById('new');
			$role->object_type=$object_type;
			$role->object_id=$object_id;
			$role->user_id=$user_id;
		};
		$role->role_id=self::$roles[$arole]['__id'];
		$role->save();
		return 'OK';
	}
	
	public function buildSQLTables(){
		obflush();
		echo "<pre>";
		echo "creating MySQL tables...\n";
		foreach(array_keys(self::$tables) as $k){
			if(!self::$tables[$k]){
				echo "trying to create table(user_$k) while model does not exist \n";
				continue;
			}
			self::$tables[$k]->buildSQL();
			echo "table(user_$k) created.\n";
		};
		$e=self::$tables['account']->getByName('admin');
		if(!$e){
			$e=self::$tables['account']->getById('new');
			$e->name='admin';
			$e->password=md5('admin');
			$e->active=1;
			$e->deleted=0;
			$e->save();
		};
		exit;
	}	
	
	
	
	
}
